home *** CD-ROM | disk | FTP | other *** search
/ Experimental BBS Explossion 3 / Experimental BBS Explossion III.iso / games / nhak_src.zip / INVENT.C < prev    next >
C/C++ Source or Header  |  1993-03-16  |  34KB  |  1,427 lines

  1. /*    SCCS Id: @(#)invent.c    3.0    88/10/22
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. #include    "hack.h"
  6.  
  7. #ifdef WORM
  8. #include "lev.h"
  9. #include "wseg.h"
  10. #endif
  11.  
  12. #define    NOINVSYM    '#'
  13.  
  14. #ifdef OVL1
  15. static boolean FDECL(mergable,(struct obj *,struct obj *));
  16. static int FDECL(merged,(struct obj *,struct obj *,int));
  17. #endif /* OVL1 */
  18. STATIC_DCL void FDECL(assigninvlet,(struct obj *));
  19. STATIC_DCL struct obj *FDECL(mkgoldobj,(long));
  20. STATIC_PTR int FDECL(ckunpaid,(struct obj *));
  21. #ifdef OVLB
  22. static boolean NDECL(wearing_armor);
  23. static boolean FDECL(is_worn,(struct obj *));
  24. #endif /* OVLB */
  25. STATIC_DCL char FDECL(obj_to_let,(struct obj *));
  26.  
  27. STATIC_DCL char *FDECL(xprname,(struct obj *,CHAR_P,BOOLEAN_P));
  28.  
  29. #ifdef OVLB
  30.  
  31. int lastinvnr = 51;    /* 0 ... 51 */
  32.  
  33. char inv_order[] = {
  34.     AMULET_SYM, WEAPON_SYM, ARMOR_SYM, FOOD_SYM, SCROLL_SYM,
  35. #ifdef SPELLS
  36.     SPBOOK_SYM,
  37. #endif
  38.     POTION_SYM, RING_SYM, WAND_SYM, TOOL_SYM, GEM_SYM,
  39.     ROCK_SYM, BALL_SYM, CHAIN_SYM, 0 };
  40.  
  41. STATIC_OVL void
  42. assigninvlet(otmp)
  43. register struct obj *otmp;
  44. {
  45.     boolean inuse[52];
  46.     register int i;
  47.     register struct obj *obj;
  48.  
  49.     for(i = 0; i < 52; i++) inuse[i] = FALSE;
  50.     for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
  51.         i = obj->invlet;
  52.         if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
  53.         if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
  54.         if(i == otmp->invlet) otmp->invlet = 0;
  55.     }
  56.     if((i = otmp->invlet) &&
  57.         (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
  58.         return;
  59.     for(i = lastinvnr+1; i != lastinvnr; i++) {
  60.         if(i == 52) { i = -1; continue; }
  61.         if(!inuse[i]) break;
  62.     }
  63.     otmp->invlet = (inuse[i] ? NOINVSYM :
  64.             (i < 26) ? ('a'+i) : ('A'+i-26));
  65.     lastinvnr = i;
  66. }
  67.  
  68. #endif /* OVLB */
  69. #ifdef OVL1
  70.  
  71. /* merge obj with otmp and delete obj if types agree */
  72. static int
  73. merged(otmp, obj, lose)
  74. register struct obj *otmp, *obj;
  75. register int lose;
  76. {
  77.     if(mergable(otmp, obj)) {
  78.         /* Approximate age: we do it this way because if we were to
  79.          * do it "accurately" (merge only when ages are identical)
  80.          * we'd wind up never merging any corpses.
  81.          * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
  82.          */
  83.         otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan))
  84.             / (otmp->quan + obj->quan);
  85.         otmp->quan += obj->quan;
  86.         otmp->owt += obj->owt;
  87.         if(!otmp->onamelth && obj->onamelth)
  88.             (void)oname(otmp, ONAME(obj), 1);
  89.         if(lose) freeobj(obj);
  90.         obfree(obj,otmp);    /* free(obj), bill->otmp */
  91.         return(1);
  92.     } else    return(0);
  93. }
  94.  
  95. struct obj *
  96. addinv(obj)
  97. register struct obj *obj;
  98. {
  99.     register struct obj *otmp;
  100.  
  101.     if (obj->otyp == AMULET_OF_YENDOR && !obj->spe) {
  102.         if (u.uhave_amulet) impossible ("already have amulet?");
  103.         u.uhave_amulet = 1;
  104.     }
  105.     /* merge or attach to end of chain */
  106.     if(!invent) {
  107.         invent = obj;
  108.         otmp = 0;
  109.     } else
  110.     for(otmp = invent; /* otmp */; otmp = otmp->nobj) {
  111.         if(merged(otmp, obj, 0)) {
  112.             obj = otmp;
  113.             goto added;
  114.         }
  115.         if(!otmp->nobj) {
  116.             otmp->nobj = obj;
  117.             break;
  118.         }
  119.     }
  120.     obj->nobj = 0;
  121.  
  122.     if(flags.invlet_constant) {
  123.         assigninvlet(obj);
  124.         /*
  125.          * The ordering of the chain is nowhere significant
  126.          * so in case you prefer some other order than the
  127.          * historical one, change the code below.
  128.          */
  129.         if(otmp) {    /* find proper place in chain */
  130.             otmp->nobj = 0;
  131.             if((invent->invlet ^ 040) > (obj->invlet ^ 040)) {
  132.                 obj->nobj = invent;
  133.                 invent = obj;
  134.             } else
  135.             for(otmp = invent; ; otmp = otmp->nobj) {
  136.                 if(!otmp->nobj ||
  137.                 (otmp->nobj->invlet ^ 040) > (obj->invlet ^ 040)){
  138.                 obj->nobj = otmp->nobj;
  139.                 otmp->nobj = obj;
  140.                 break;
  141.                 }
  142.             }
  143.         }
  144.     }
  145.  
  146. added:
  147.     if (obj->otyp == LUCKSTONE) {
  148.         /* new luckstone must be in inventory by this point
  149.          * for correct calculation */
  150.         if (stone_luck(TRUE) >= 0) u.moreluck = LUCKADD;
  151.         else u.moreluck = -LUCKADD;
  152.     }
  153.     return(obj);
  154. }
  155.  
  156. #endif /* OVL1 */
  157. #ifdef OVLB
  158.  
  159. void
  160. useup(obj)
  161. register struct obj *obj;
  162. {
  163.     if(obj->quan > 1){
  164. #ifndef NO_SIGNAL
  165.         obj->in_use = FALSE;    /* no longer in use */
  166. #endif
  167.         obj->quan--;
  168.         obj->owt = weight(obj);
  169.     } else {
  170.         if(obj->otyp == CORPSE) food_disappears(obj);
  171.         setnotworn(obj);
  172.         freeinv(obj);
  173.         delete_contents(obj);
  174.         obfree(obj, (struct obj *) 0);
  175.     }
  176. }
  177.  
  178. #endif /* OVLB */
  179. #ifdef OVL3
  180.  
  181. void
  182. freeinv(obj)
  183. register struct obj *obj;
  184. {
  185.     register struct obj *otmp;
  186.  
  187.     if(obj == invent)
  188.         invent = invent->nobj;
  189.     else {
  190.         for(otmp = invent; otmp->nobj != obj; otmp = otmp->nobj)
  191.             if(!otmp->nobj) panic("freeinv");
  192.         otmp->nobj = obj->nobj;
  193.     }
  194.     if (obj->otyp == AMULET_OF_YENDOR && !obj->spe) {
  195.         if (!u.uhave_amulet) impossible ("don't have amulet?");
  196.         u.uhave_amulet = 0;
  197.     }
  198.     if (obj->otyp == LOADSTONE)
  199.         curse(obj);
  200.     if (obj->otyp == LUCKSTONE) {
  201.         if (!carrying(LUCKSTONE)) u.moreluck = 0;
  202.         else if (stone_luck(TRUE) >= 0) u.moreluck = LUCKADD;
  203.         else u.moreluck = -LUCKADD;
  204.         flags.botl = 1;
  205.     }
  206. }
  207.  
  208. #endif /* OVL3 */
  209. #ifdef OVL2
  210.  
  211. /* destroy object in fobj chain (if unpaid, it remains on the bill) */
  212. void
  213. delobj(obj)
  214. register struct obj *obj;
  215. {
  216. #ifdef WALKIES
  217.     if(obj->otyp == LEASH && obj->leashmon != 0) o_unleash(obj);
  218. #endif
  219.     if(obj->otyp == CORPSE) food_disappears(obj);
  220.  
  221.     freeobj(obj);
  222.     unpobj(obj);
  223.  
  224. /*    if a container, get rid of the contents */
  225.     delete_contents(obj);
  226.  
  227.     obfree(obj, (struct obj *) 0);
  228. }
  229.  
  230. /* unlink obj from chain starting with fobj */
  231. void
  232. freeobj(obj)
  233. register struct obj *obj;
  234. {
  235.     register struct obj *otmp;
  236.     register int found = 0;
  237.  
  238.     if(obj == fobj) {
  239.         fobj = fobj->nobj;
  240.         found = 1;
  241.     }
  242.     for(otmp = fobj; otmp; otmp = otmp->nobj)
  243.          if (otmp->nobj == obj) {
  244.         otmp->nobj = obj->nobj;
  245.         found = 1;
  246.         }
  247.       if (!found) panic("error in freeobj");
  248.     remove_object(obj);
  249. #ifdef POLYSELF
  250.     if (!OBJ_AT(u.ux, u.uy) && !levl[u.ux][u.uy].gmask) {
  251.         u.uundetected = 0;
  252.         if (!Invisible) pru();
  253.     }
  254. #endif
  255. }
  256.  
  257. /* Note: freegold throws away its argument! */
  258. void
  259. freegold(gold)
  260. register struct gold *gold;
  261. {
  262.     register struct gold *gtmp;
  263.  
  264.     levl[gold->gx][gold->gy].gmask = 0;
  265.  
  266.     if(gold == fgold) fgold = gold->ngold;
  267.     else {
  268.         for(gtmp = fgold; gtmp->ngold != gold; gtmp = gtmp->ngold)
  269.             if(!gtmp) panic("error in freegold");
  270.         gtmp->ngold = gold->ngold;
  271.     }
  272.     free((genericptr_t) gold);
  273. #ifdef POLYSELF
  274.     if (!OBJ_AT(u.ux, u.uy) && !levl[u.ux][u.uy].gmask) {
  275.         u.uundetected = 0;
  276.         if (!Invisible) pru();
  277.     }
  278. #endif
  279. }
  280.  
  281. #endif /* OVL2 */
  282. #ifdef OVL0
  283.  
  284. struct obj *
  285. sobj_at(n,x,y)
  286. register int n, x, y;
  287. {
  288.     register struct obj *otmp;
  289.  
  290.     for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
  291.         if(otmp->otyp == n)
  292.             return(otmp);
  293.     return((struct obj *)0);
  294. }
  295.  
  296. #endif /* OVL0 */
  297. #ifdef OVLB
  298.  
  299. int
  300. carried(obj)
  301. register struct obj *obj;
  302. {
  303.     register struct obj *otmp;
  304.  
  305.     for(otmp = invent; otmp; otmp = otmp->nobj)
  306.         if(otmp == obj) return(1);
  307.     return(0);
  308. }
  309.  
  310. struct obj *
  311. carrying(type)
  312. register int type;
  313. {
  314.     register struct obj *otmp;
  315.  
  316.     for(otmp = invent; otmp; otmp = otmp->nobj)
  317.         if(otmp->otyp == type)
  318.             return(otmp);
  319.     return((struct obj *) 0);
  320. }
  321.  
  322. boolean
  323. have_lizard()
  324. {
  325.     register struct obj *otmp;
  326.  
  327.     for(otmp = invent; otmp; otmp = otmp->nobj)
  328.         if(otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
  329.             return(TRUE);
  330.     return(FALSE);
  331. }
  332.  
  333. struct obj *
  334. o_on(id, objchn)
  335. unsigned int id;
  336. register struct obj *objchn;
  337. {
  338.     while(objchn) {
  339.         if(objchn->o_id == id) return(objchn);
  340.         objchn = objchn->nobj;
  341.     }
  342.     return((struct obj *) 0);
  343. }
  344.  
  345. boolean
  346. obj_here(obj, x, y)
  347. register struct obj *obj;
  348. int x, y;
  349. {
  350.     register struct obj *otmp;
  351.  
  352.     for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
  353.         if(obj == otmp) return(TRUE);
  354.     return(FALSE);
  355. }
  356.  
  357. #endif /* OVLB */
  358. #ifdef OVL2
  359.  
  360. struct gold *
  361. g_at(x,y)
  362. register int x, y;
  363. {
  364.     register struct gold *gold = fgold;
  365.     while(gold) {
  366.         if(gold->gx == x && gold->gy == y) return(gold);
  367.         gold = gold->ngold;
  368.     }
  369.     return((struct gold *)0);
  370. }
  371.  
  372. #endif /* OVL2 */
  373. #ifdef OVLB
  374.  
  375. /* make dummy object structure containing gold - for temporary use only */
  376. STATIC_OVL
  377. struct obj *
  378. mkgoldobj(q)
  379. register long q;
  380. {
  381.     register struct obj *otmp;
  382.  
  383.     otmp = newobj(0);
  384.     /* should set o_id etc. but otmp will be freed soon */
  385.     otmp->olet = GOLD_SYM;
  386. #ifdef POLYSELF
  387.     otmp->ox = 0; /* necessary for eating gold */
  388. #endif
  389.     u.ugold -= q;
  390.     OGOLD(otmp) = q;
  391.     flags.botl = 1;
  392.     return(otmp);
  393. }
  394.  
  395. #endif /* OVLB */
  396. #ifdef OVL1
  397.  
  398. /*
  399.  * getobj returns:
  400.  *    struct obj *xxx:    object to do something with.
  401.  *    (struct obj *) 0    error return: no object.
  402.  *    &zeroobj        explicitly no object (as in w-).
  403.  */
  404. struct obj *
  405. getobj(let,word)
  406. register const char *let,*word;
  407. {
  408.     register struct obj *otmp;
  409.     register char ilet,ilet1,ilet2;
  410.     char buf[BUFSZ];
  411.     char lets[BUFSZ];
  412.     register int foo = 0, foo2;
  413.     register char *bp = buf;
  414.     xchar allowcnt = 0;    /* 0, 1 or 2 */
  415.     boolean allowgold = FALSE, usegold = FALSE;
  416.         /* usegold is needed so that they are given a different message
  417.          * if gold is prohibited because it's inappropriate, or because
  418.          * it's appropriate if only they had any.
  419.          */
  420.     boolean allowall = FALSE;
  421.     boolean allownone = FALSE;
  422.     xchar foox = 0;
  423.     long cnt;
  424.     boolean prezero = FALSE;
  425.  
  426.     if(*let == '0') let++, allowcnt = 1;
  427.     if(*let == GOLD_SYM) let++,
  428.         usegold = TRUE, allowgold = (u.ugold ? TRUE : FALSE);
  429. #ifdef POLYSELF
  430.     /* Equivalent of an "ugly check" for gold */
  431.     if (usegold && !strcmp(word, "eat") && !metallivorous(uasmon))
  432.         usegold = allowgold = FALSE;
  433. #endif
  434.     if(*let == '#') let++, allowall = TRUE;
  435.     if(*let == '-') let++, allownone = TRUE;
  436.     if(allownone) *bp++ = '-';
  437.     if(allowgold) *bp++ = GOLD_SYM;
  438.     if(bp > buf && bp[-1] == '-') *bp++ = ' ';
  439.  
  440.     ilet = 'a';
  441.     for(otmp = invent; otmp; otmp = otmp->nobj){
  442.         if(!*let || index(let, otmp->olet)) {
  443.         bp[foo++] = flags.invlet_constant ? otmp->invlet : ilet;
  444.  
  445.         /* ugly check: remove inappropriate things */
  446.         if((!strcmp(word, "take off") &&
  447.             (!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL))
  448.              || (otmp==uarm && uarmc)
  449. #ifdef SHIRT
  450.              || (otmp==uarmu && (uarm || uarmc))
  451. #endif
  452.             ))
  453.         || (!strcmp(word, "wear") &&
  454.              (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
  455.                             /* already worn */
  456.         || (!strcmp(word, "wield") &&
  457.             (otmp->owornmask & W_WEP))
  458.             ) {
  459.             foo--;
  460.             foox++;
  461.         }
  462.  
  463.         /* Second ugly check; unlike the first it won't trigger an
  464.          * "else" in "you don't have anything else to ___".
  465.          */
  466.         else if ((!strcmp(word, "wear") &&
  467.             (otmp->olet == TOOL_SYM && otmp->otyp != BLINDFOLD))
  468. #ifdef POLYSELF
  469.         || (!strcmp(word, "eat") && !is_edible(otmp))
  470. #endif
  471.         || (!strcmp(word, "can") &&
  472.             (otmp->otyp != CORPSE))
  473.         || (!strcmp(word, "write with") &&
  474.             (otmp->olet == TOOL_SYM && otmp->otyp != MAGIC_MARKER))
  475.         || (!strcmp(word, "rub") &&
  476.             (otmp->olet == TOOL_SYM &&
  477.              otmp->otyp != LAMP && otmp->otyp != MAGIC_LAMP))
  478.         || (!strcmp(word, "wield") &&
  479.             (otmp->olet == TOOL_SYM &&
  480.              otmp->otyp != PICK_AXE && otmp->otyp != UNICORN_HORN))
  481.             )
  482.             foo--;
  483.         }
  484.         if(ilet == 'z') ilet = 'A'; else ilet++;
  485.     }
  486.     bp[foo] = 0;
  487.     if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
  488.     Strcpy(lets, bp);    /* necessary since we destroy buf */
  489.     if(foo > 5) {            /* compactify string */
  490.         foo = foo2 = 1;
  491.         ilet2 = bp[0];
  492.         ilet1 = bp[1];
  493.         while(ilet = bp[++foo2] = bp[++foo]){
  494.             if(ilet == ilet1+1){
  495.                 if(ilet1 == ilet2+1)
  496.                     bp[foo2 - 1] = ilet1 = '-';
  497.                 else if(ilet2 == '-') {
  498.                     bp[--foo2] = ++ilet1;
  499.                     continue;
  500.                 }
  501.             }
  502.             ilet2 = ilet1;
  503.             ilet1 = ilet;
  504.         }
  505.     }
  506.     if(!foo && !allowall && !allowgold && !allownone) {
  507.         You("don't have anything %sto %s.",
  508.             foox ? "else " : "", word);
  509.         return((struct obj *)0);
  510.     }
  511.     for(;;) {
  512. #ifdef MACOS
  513.         short    tmpflags;
  514.         extern short macflags;
  515.         
  516.         tmpflags = macflags;
  517.         macflags &= ~fDoNonKeyEvt;
  518. #endif
  519.         if(!buf[0]) {
  520. #ifdef REDO
  521.             if(!in_doagain)
  522. #endif
  523.             pline("What do you want to %s? [*] ", word);
  524.         } else {
  525. #ifdef REDO
  526.             if(!in_doagain)
  527. #endif
  528.             pline("What do you want to %s? [%s or ?*] ",
  529.                 word, buf);
  530.         }
  531.         cnt = 0;
  532.         ilet = readchar();
  533.         if(ilet == '0') prezero = TRUE;
  534.         while(digit(ilet) && allowcnt) {
  535. #ifdef REDO
  536.             if (ilet != '?' && ilet != '*')    savech(ilet);
  537. #endif
  538.             cnt = 10*cnt + (ilet - '0');
  539.             allowcnt = 2;    /* signal presence of cnt */
  540.             ilet = readchar();
  541.         }
  542. #ifdef MACOS
  543.         macflags = tmpflags;
  544. #endif
  545.         if(digit(ilet)) {
  546.             pline("No count allowed with this command.");
  547.             continue;
  548.         }
  549.         if(index(quitchars,ilet)) {
  550.             if(flags.verbose)
  551.             pline("Never mind.");
  552.             return((struct obj *)0);
  553.         }
  554.         if(ilet == '-') {
  555.             return(allownone ? &zeroobj : (struct obj *) 0);
  556.         }
  557.         if(ilet == GOLD_SYM) {
  558.             if(!usegold){
  559.                 You("cannot %s gold.", word);
  560.                 return(struct obj *)0;
  561.             } else if (!allowgold) {
  562.                 You("are not carrying any gold.");
  563.                 return(struct obj *)0;
  564.             }
  565.             if(cnt == 0 && prezero) return((struct obj *)0);
  566.             if(!(allowcnt == 2 && cnt < u.ugold))
  567.                 cnt = u.ugold;
  568.             return(mkgoldobj(cnt));
  569.         }
  570.         if(allowcnt == 2 && !strcmp(word,"throw")) {
  571.             /* permit counts for throwing gold, but don't accept
  572.              * counts for other things since the throw code will
  573.              * split off a single item anyway */
  574.             allowcnt = 1;
  575.             if(cnt == 0 && prezero) return((struct obj *)0);
  576.             if(cnt > 1) {
  577.                 You("can only throw one item at a time.");
  578.                 continue;
  579.             }
  580.         }
  581.         if(ilet == '?') {
  582.             doinv(lets);
  583.             if(!(ilet = morc)) continue;
  584.             /* he typed a letter (not a space) to more() */
  585.         } else if(ilet == '*') {
  586.             doinv(NULL);
  587.             if(!(ilet = morc)) continue;
  588.             /* ... */
  589.         }
  590. #ifdef REDO
  591.         if (ilet != '?' && ilet != '*')    savech(ilet);
  592. #endif
  593.         if(flags.invlet_constant) {
  594.             for(otmp = invent; otmp; otmp = otmp->nobj)
  595.                 if(otmp->invlet == ilet) break;
  596.         } else {
  597.             if(ilet >= 'A' && ilet <= 'Z') ilet += 'z'-'A'+1;
  598.             ilet -= 'a';
  599.             for(otmp = invent; otmp && ilet;
  600.                     ilet--, otmp = otmp->nobj) ;
  601.         }
  602.         if(!otmp) {
  603.             You("don't have that object.");
  604.             continue;
  605.         }
  606.         if(cnt < 0 || otmp->quan < cnt) {
  607.             You("don't have that many!  You have only %u."
  608.             , otmp->quan);
  609.             continue;
  610.         }
  611.         break;
  612.     }
  613.     if(!allowall && let && !index(let,otmp->olet)) {
  614.         pline("That is a silly thing to %s.",word);
  615.         return((struct obj *)0);
  616.     }
  617.     if(allowcnt == 2) {    /* cnt given */
  618.         if(cnt == 0) return (struct obj *)0;
  619.         if(cnt != otmp->quan) {
  620.             register struct obj *obj;
  621.             
  622. #ifdef LINT    /*splitobj for (long )cnt > 30000 && sizeof(int) == 2*/
  623.             obj = (struct obj *)0;
  624. #else
  625.             if (sizeof(int) == 2)
  626.                 obj = splitobj(otmp,
  627.                     (int )(cnt >30000 ? 30000 : cnt));
  628.             else
  629.                 obj = splitobj(otmp, (int) cnt);
  630. #endif
  631.         /* Very ugly kludge necessary to prevent someone from trying
  632.          * to drop one of several loadstones and having the loadstone
  633.          * now be separate.  If putting items in containers is ever
  634.          * changed to allow putting in counts of individual items, a
  635.          * similar kludge will be needed.
  636.          */
  637.             if (!strcmp(word, "drop") && obj->otyp == LOADSTONE
  638.                     && obj->cursed)
  639.                 otmp->corpsenm = obj->invlet;
  640.             if(otmp == uwep) setuwep(obj);
  641.         }
  642.     }
  643.     return(otmp);
  644. }
  645.  
  646. #endif /* OVL1 */
  647. #ifdef OVLB
  648.  
  649. STATIC_PTR int
  650. ckunpaid(otmp)
  651. register struct obj *otmp;
  652. {
  653.     return((int)(otmp->unpaid));
  654. }
  655.  
  656. static boolean
  657. wearing_armor() {
  658.     return(uarm || uarmc || uarmf || uarmg || uarmh || uarms
  659. #ifdef SHIRT
  660.         || uarmu
  661. #endif
  662.         );
  663. }
  664.  
  665. static boolean
  666. is_worn(otmp)
  667. register struct obj *otmp;
  668. {
  669.     return(!!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL | W_WEP)));
  670. }
  671.  
  672. static const char NEARDATA removeables[] =
  673.     { ARMOR_SYM, WEAPON_SYM, RING_SYM, AMULET_SYM, TOOL_SYM, ' ', 0 };
  674.  
  675. /* interactive version of getobj - used for Drop, Identify and */
  676. /* Takeoff (A). Return the number of times fn was called successfully */
  677. int
  678. ggetobj(word, fn, mx)
  679. register const char *word;
  680. register int FDECL((*fn),(struct obj *)), mx;
  681. {
  682.     char buf[BUFSZ];
  683.     register char *ip;
  684.     register char sym;
  685.     register int oletct = 0, iletct = 0;
  686.     register boolean allflag = FALSE;
  687.     char olets[20], ilets[20];
  688.     int FDECL((*ckfn),(struct obj *)) = (int (*)()) 0;
  689.     xchar allowgold = (u.ugold && !strcmp(word, "drop")) ? 1 : 0; /* BAH */
  690.     register boolean takeoff = !strcmp(word, "take off");
  691.  
  692.     if(takeoff && !wearing_armor() && !uwep && !uamul &&
  693.             !uleft && !uright && !ublindf) {
  694.         You("are not wearing anything.");
  695.         return(0);
  696.     }
  697.     if(!invent && !allowgold){
  698.         You("have nothing to %s.", word);
  699.         return(0);
  700.     } else {
  701.         register struct obj *otmp = invent;
  702.         register int uflg = 0;
  703.  
  704.         if(allowgold) ilets[iletct++] = GOLD_SYM;
  705.         ilets[iletct] = 0;
  706.         while(otmp) {
  707.             if(!index(ilets, otmp->olet)){
  708.                 if(!takeoff || is_worn(otmp))
  709.                 ilets[iletct++] = otmp->olet;
  710.                 ilets[iletct] = 0;
  711.             }
  712.             if(otmp->unpaid) uflg = 1;
  713.             otmp = otmp->nobj;
  714.         }
  715.         ilets[iletct++] = ' ';
  716.         if(uflg && !takeoff) ilets[iletct++] = 'u';
  717.         if(invent && !takeoff) ilets[iletct++] = 'a';
  718.         ilets[iletct] = 0;
  719.     }
  720.     pline("What kinds of thing do you want to %s? [%s] ",
  721.         word, ilets);
  722.     getlin(buf);
  723.     if(buf[0] == '\033') {
  724.         clrlin();
  725.         return(0);
  726.     }
  727.     ip = buf;
  728.     olets[0] = 0;
  729.     while(sym = *ip++){
  730.         if(sym == ' ') continue;
  731.         if(takeoff && !(uwep && sym == uwep->olet)) {
  732.             if(!index(removeables,sym)) {
  733.             pline("Not applicable.");
  734.             return(0);
  735.             } else if(sym == ARMOR_SYM && !wearing_armor()) {
  736.             You("are not wearing any armor.");
  737.             return(0);
  738.             } else if(sym == WEAPON_SYM && !uwep) {
  739.             You("are not wielding anything.");
  740.             return(0);
  741.             } else if(sym == RING_SYM && !uright && !uleft) {
  742.             You("are not wearing rings.");
  743.             return(0);
  744.             } else if(sym == AMULET_SYM && !uamul) {
  745.             You("are not wearing an amulet.");
  746.             return(0);
  747.             } else if(sym == TOOL_SYM && !ublindf) {
  748.             You("are not wearing a blindfold.");
  749.             return(0);
  750.             }
  751.         }
  752.         if(sym == GOLD_SYM) {
  753.             if(allowgold == 1)
  754.                 (*fn)(mkgoldobj(u.ugold));
  755.             else if(!u.ugold)
  756.                 You("have no gold.");
  757.             allowgold = 2;
  758.         } else if(sym == 'a' || sym == 'A')
  759.             allflag = TRUE;
  760.         else if(sym == 'u' || sym == 'U')
  761.             ckfn = ckunpaid;
  762.         else if(index(inv_order, sym)) {
  763.             if(!index(olets, sym)) {
  764.                 olets[oletct++] = sym;
  765.                 olets[oletct] = 0;
  766.             }
  767.         } else You("don't have any %c's.", sym);
  768.     }
  769.     if(allowgold == 2 && !oletct)
  770.         return(1);    /* he dropped gold (or at least tried to) */
  771.     else
  772.         return(askchain(invent, TRUE, olets, allflag, fn, ckfn, mx, word));
  773. }
  774.  
  775. /*
  776.  * Walk through the chain starting at objchn and ask for all objects
  777.  * with olet in olets (if nonNULL) and satisfying ckfn (if nonNULL)
  778.  * whether the action in question (i.e., fn) has to be performed.
  779.  * If allflag then no questions are asked. Max gives the max nr of
  780.  * objects to be treated. Return the number of objects treated.
  781.  * If ininv is TRUE, the objects are in the player's inventory.
  782.  */
  783. int
  784. askchain(objchn, ininv, olets, allflag, fn, ckfn, mx, word)
  785. register struct obj *objchn;
  786. register int ininv, allflag, mx;
  787. register const char *olets, *word;
  788. register int FDECL((*fn),(struct obj *)), FDECL((*ckfn),(struct obj *));
  789. {
  790.     register struct obj *otmp, *otmp2;
  791.     register char sym, ilet;
  792.     register int cnt = 0, dud = 0;
  793.     register boolean takeoff, nodot;
  794.  
  795.     takeoff = !strcmp(word, "take off");
  796.     nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") ||
  797.                !strcmp(word, "identify") || takeoff);
  798.     /* changes so the askchain is interrogated in the order specified.
  799.      * For example, if a person specifies =/ then first all rings will be
  800.      * asked about followed by all wands -dgk
  801.      */
  802. nextclass:
  803.     ilet = 'a'-1;
  804.     for(otmp = (ininv ? invent : objchn); otmp; otmp = otmp2){
  805.         if(ilet == 'z') ilet = 'A'; else ilet++;
  806.         otmp2 = otmp->nobj;
  807.         if (olets && *olets && otmp->olet != *olets) continue;
  808.         if(takeoff && !is_worn(otmp)) continue;
  809.         if(ckfn && !(*ckfn)(otmp)) continue;
  810.         if(!allflag) {
  811.             if(ininv)
  812.                 pline("%s", xprname(otmp, ilet,
  813.                             nodot ? FALSE : TRUE));
  814.             else
  815.                 pline(doname(otmp));
  816.             addtopl("? ");
  817.             sym = nyaq();
  818.         }
  819.         else    sym = 'y';
  820.  
  821.         switch(sym){
  822.         case 'a':
  823.             allflag = 1;
  824.         case 'y':
  825.             cnt += (*fn)(otmp);
  826.             if(--mx == 0) goto ret;
  827.         case 'n':
  828.             if(nodot) dud++;
  829.         default:
  830.             break;
  831.         case 'q':
  832.             goto ret;
  833.         }
  834.     }
  835.     if (olets && *olets && *++olets)
  836.         goto nextclass;
  837.     if(!takeoff && (dud || cnt)) pline("That was all.");
  838.     else if(!dud && !cnt) pline("No applicable objects.");
  839. ret:
  840.     return(cnt);
  841. }
  842.  
  843. #endif /* OVLB */
  844. #ifdef OVL2
  845.  
  846. STATIC_OVL
  847. char
  848. obj_to_let(obj)    /* should of course only be called for things in invent */
  849. register struct obj *obj;
  850. {
  851.     register struct obj *otmp;
  852.     register char ilet;
  853.  
  854.     if(flags.invlet_constant)
  855.         return(obj->invlet);
  856.     ilet = 'a';
  857.     for(otmp = invent; otmp && otmp != obj; otmp = otmp->nobj)
  858.         if(++ilet > 'z') ilet = 'A';
  859.     return(otmp ? ilet : NOINVSYM);
  860. }
  861.  
  862. void
  863. prinv(obj)
  864. register struct obj *obj;
  865. {
  866.     pline(xprname(obj, obj_to_let(obj), TRUE));
  867. }
  868.  
  869. #endif /* OVL2 */
  870. #ifdef OVL1
  871.  
  872. STATIC_OVL char *
  873. xprname(obj,let,dot)
  874. register struct obj *obj;
  875. register char let;
  876. register boolean dot;
  877. {
  878. #ifdef LINT    /* handle static char li[BUFSZ]; */
  879.     char li[BUFSZ];
  880. #else
  881.     static char li[BUFSZ];
  882. #endif
  883.  
  884.     Sprintf(li, "%c - %s",
  885.         (flags.invlet_constant ? obj->invlet : let),
  886.         doname(obj));
  887.     if(dot) Sprintf(eos(li),".");
  888.     return(li);
  889. }
  890.  
  891. #endif /* OVL1 */
  892. #ifdef OVLB
  893.  
  894. int
  895. ddoinv()
  896. {
  897.     doinv(NULL);
  898.     return 0;
  899. }
  900.  
  901. #endif /* OVLB */
  902. #ifdef OVL1
  903.  
  904. /* called with 0 or "": all objects in inventory */
  905. /* otherwise: all objects with (serial) letter in lets */
  906. void
  907. doinv(lets)
  908. register const char *lets;
  909. {
  910.     register struct obj *otmp;
  911.     register char ilet;
  912.     int ct = 0;
  913.     char any[BUFSZ];
  914.     char *invlet = inv_order;
  915.     int classcount = 0;
  916.  
  917.     morc = 0;        /* just to be sure */
  918.  
  919.     if(!invent){
  920.         pline("Not carrying anything.");
  921.         return;
  922.     }
  923.     if (lets != NULL) {
  924.         for(ct=0; lets[ct]; ct++) {
  925.             if (ct >= 52) {
  926.                 impossible("bad lets contents");
  927.                 break;
  928.             }
  929.         }
  930.         if (ct==1) {
  931.             ilet = 'a';
  932.             for(otmp = invent; otmp; otmp = otmp->nobj) {
  933.                 if(flags.invlet_constant) ilet = otmp->invlet;
  934.  
  935.                 if (ilet == lets[0])
  936.                     pline(xprname(otmp, lets[0], TRUE));
  937.  
  938.                 if(!flags.invlet_constant)
  939.                     if(++ilet > 'z') ilet = 'A';
  940.             }
  941.             return;
  942.         }
  943.     }
  944.     ct = 0;
  945.  
  946.     cornline(0, NULL);
  947. nextclass:
  948.     classcount = 0;
  949.     ilet = 'a';
  950.     for(otmp = invent; otmp; otmp = otmp->nobj) {
  951.         if(flags.invlet_constant) ilet = otmp->invlet;
  952.         if(!lets || !*lets || index(lets, ilet)) {
  953.             if (!flags.sortpack || otmp->olet == *invlet) {
  954.                 if (flags.sortpack && !classcount) {
  955.                     cornline(1, let_to_name(*invlet));
  956.                     classcount++;
  957.                 }
  958.                 cornline(1, xprname(otmp, ilet, TRUE));
  959.                 any[ct++] = ilet;
  960.             }
  961.         }
  962.         if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
  963.     }
  964.     if (flags.sortpack && *++invlet) goto nextclass;
  965.     any[ct] = 0;
  966.     cornline(2, any);
  967. }
  968.  
  969. #endif /* OVL1 */
  970. #ifdef OVLB
  971.  
  972. int
  973. dotypeinv()                /* free after Robert Viduya */
  974. /* Changed to one type only, so he doesn't have to type cr */
  975. {
  976.         char c, ilet;
  977.         char stuff[BUFSZ];
  978.         register int stct;
  979.         register struct obj *otmp;
  980.         boolean billx = in_shop(u.ux, u.uy) && doinvbill(0);
  981.         boolean unpd = FALSE;
  982.  
  983.     if (!invent && !u.ugold && !billx) {
  984.         You("aren't carrying anything.");
  985.         return 0;
  986.     }
  987.  
  988.     stct = 0;
  989.     if(u.ugold) stuff[stct++] = GOLD_SYM;
  990.     stuff[stct] = 0;
  991.     for(otmp = invent; otmp; otmp = otmp->nobj) {
  992.         if (!index (stuff, otmp->olet)) {
  993.         stuff[stct++] = otmp->olet;
  994.         stuff[stct] = 0;
  995.         }
  996.         if(otmp->unpaid)
  997.         unpd = TRUE;
  998.     }
  999.     if(unpd) stuff[stct++] = 'u';
  1000.     if(billx) stuff[stct++] = 'x';
  1001.     stuff[stct] = 0;
  1002.  
  1003.     if(stct > 1) {
  1004. #ifdef REDO
  1005.       if (!in_doagain)
  1006. #endif
  1007.         pline ("What type of object do you want an inventory of? [%s] ",
  1008.             stuff);
  1009.         c = readchar();
  1010. #ifdef REDO
  1011.         savech(c);
  1012. #endif
  1013.         if(index(quitchars,c)) {
  1014.                 clrlin();
  1015.                 return 0;
  1016.         }
  1017.     } else
  1018.         c = stuff[0];
  1019.  
  1020.     if(c == GOLD_SYM)
  1021.         return(doprgold());
  1022.  
  1023.     if(c == 'x' || c == 'X') {
  1024.         if(billx)
  1025.         (void) doinvbill(1);
  1026.         else
  1027.         pline("No used-up objects on the shopping bill.");
  1028.         return(0);
  1029.     }
  1030.  
  1031.     if((c == 'u' || c == 'U') && !unpd) {
  1032.         You("are not carrying any unpaid objects.");
  1033.         return(0);
  1034.     }
  1035.  
  1036.     stct = 0;
  1037.     ilet = 'a';
  1038.     for (otmp = invent; otmp; otmp = otmp -> nobj) {
  1039.         if(flags.invlet_constant) ilet = otmp->invlet;
  1040.         if (c == otmp -> olet || (c == 'u' && otmp -> unpaid))
  1041.         stuff[stct++] = ilet;
  1042.         if(!flags.invlet_constant) if(++ilet > 'z') ilet = 'A';
  1043.     }
  1044.     stuff[stct] = '\0';
  1045.     if(stct == 0)
  1046.         You("have no such objects.");
  1047.     else
  1048.         doinv (stuff);
  1049.  
  1050.     return(0);
  1051. }
  1052.  
  1053. /* look at what is here */
  1054. int
  1055. dolook() {
  1056.         register struct obj *otmp, *otmp0;
  1057.         register struct gold *gold;
  1058.         const char *verb = Blind ? "feel" : "see";
  1059.         int ct = 0;
  1060.         int fd = 0;
  1061.  
  1062.         read_engr_at(u.ux, u.uy); /* Eric Backus */
  1063.         if(!u.uswallow) {
  1064.         otmp0 = level.objects[u.ux][u.uy];
  1065.         gold = g_at(u.ux, u.uy);
  1066.         }  else  {
  1067.         You("%s no objects here.", verb);
  1068.         return(!!Blind);
  1069.         }
  1070.  
  1071.     if(IS_DOOR(levl[u.ux][u.uy].typ))  {
  1072.         fd++;
  1073.         switch(levl[u.ux][u.uy].doormask) {
  1074.             case D_NODOOR:
  1075.             pline("There is a doorway here."); break;
  1076.             case D_ISOPEN:
  1077.             pline("There is an open door here."); break;
  1078.             case D_BROKEN:
  1079.             pline("There is a broken door here."); break;
  1080.             default:
  1081.             pline("There is a closed door here.");
  1082.         }
  1083.     }
  1084.         /* added by GAN 10/30/86 */
  1085. #ifdef FOUNTAINS
  1086.         if(IS_FOUNTAIN(levl[u.ux][u.uy].typ))  {
  1087.         fd++;
  1088.         pline("There is a fountain here.");
  1089.         }
  1090. #endif
  1091. #ifdef THRONES
  1092.         if(IS_THRONE(levl[u.ux][u.uy].typ))  {
  1093.         fd++;
  1094.         pline("There is an opulent throne here.");
  1095.         }
  1096. #endif
  1097. #ifdef SINKS
  1098.         if(IS_SINK(levl[u.ux][u.uy].typ))  {
  1099.         fd++;
  1100.         pline("There is a kitchen sink here.");
  1101.         }
  1102. #endif
  1103. #ifdef ALTARS
  1104.         if(IS_ALTAR(levl[u.ux][u.uy].typ))  {
  1105.         const char *al;
  1106.  
  1107.         fd++;
  1108.         switch (levl[u.ux][u.uy].altarmask & ~A_SHRINE) {
  1109.             case 0: al = "chaotic"; break;
  1110.             case 1: al = "neutral"; break;
  1111.             default: al = "lawful"; break;
  1112.         }
  1113.         pline("There is an altar to %s here (%s).", a_gname(), al);
  1114.         }
  1115. #endif
  1116.  
  1117.         if(u.ux == xupstair && u.uy == yupstair)  {
  1118.         fd++;
  1119.         pline("There is a stairway up here.");
  1120.         }
  1121.         if(u.ux == xdnstair && u.uy == ydnstair)  {
  1122.         fd++;
  1123.         pline("There is a stairway down here.");
  1124.         }
  1125. #ifdef STRONGHOLD
  1126.         if(u.ux == xupladder && u.uy == yupladder)    {
  1127.         fd++;
  1128.         pline("There is a ladder up here.");
  1129.         }
  1130.         if(u.ux == xdnladder && u.uy == ydnladder)    {
  1131.         fd++;
  1132.         pline("There is a ladder down here.");
  1133.         }
  1134.         if (levl[u.ux][u.uy].typ == DRAWBRIDGE_DOWN) {
  1135.         fd++;
  1136.         pline("There is a lowered drawbridge here.");
  1137.         }
  1138. #endif /* STRONGHOLD /**/
  1139.  
  1140.         if(Blind)  {
  1141.         You("try to feel what is lying here on the floor.");
  1142.          if(Levitation)  {
  1143.             pline("But you can't reach it!");
  1144.             return(0);
  1145.          }
  1146.         }
  1147.  
  1148.         if(!otmp0 && !gold) {
  1149.         if(Blind || !fd)
  1150.             You("%s no objects here.", verb);
  1151.         return(!!Blind);
  1152.         }
  1153.  
  1154.         cornline(0, "Things that are here:");
  1155.         for(otmp = otmp0; otmp; otmp = otmp->nexthere) {
  1156.         ct++;
  1157.         cornline(1, doname(otmp));
  1158.  
  1159.         if(Blind  && !uarmg &&
  1160. #ifdef POLYSELF
  1161.             !resists_ston(uasmon) &&
  1162. #endif
  1163.             (otmp->otyp == CORPSE && otmp->corpsenm == PM_COCKATRICE)) {
  1164.             pline("Touching the dead cockatrice is a fatal mistake...");
  1165.             You("turn to stone...");
  1166.             killer_format = KILLED_BY_AN;
  1167.             killer = "cockatrice corpse";
  1168.             done(STONING);
  1169.         }
  1170.     }
  1171.  
  1172.         if(gold) {
  1173.         char gbuf[30];
  1174.  
  1175.         Sprintf(gbuf, "%ld gold piece%s",
  1176.             gold->amount, plur(gold->amount));
  1177.         if(!ct++)
  1178.                 You("%s here %s.", verb, gbuf);
  1179.         else
  1180.                 cornline(1, gbuf);
  1181.         }
  1182.  
  1183.         if(ct == 1 && !gold) {
  1184.         You("%s here %s.", verb, doname(otmp0));
  1185.         cornline(3, NULL);
  1186.         }
  1187.         if(ct > 1)
  1188.         cornline(2, NULL);
  1189.         return(!!Blind);
  1190. }
  1191.  
  1192. #endif /* OVLB */
  1193. #ifdef OVL1
  1194.  
  1195. void
  1196. stackobj(obj)
  1197. register struct obj *obj;
  1198. {
  1199.     register struct obj *otmp;
  1200.  
  1201.     for(otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
  1202.         if(otmp != obj && merged(obj,otmp,1))
  1203.             break;
  1204.     return;
  1205. }
  1206.  
  1207. static boolean
  1208. mergable(otmp, obj)    /* returns TRUE if obj  & otmp can be merged */
  1209.     register struct obj *otmp, *obj;
  1210. {
  1211.     if(obj->otyp != otmp->otyp || obj->unpaid != otmp->unpaid ||
  1212.        obj->spe != otmp->spe || obj->dknown != otmp->dknown ||
  1213.        (obj->bknown != otmp->bknown && pl_character[0] != 'P') ||
  1214.        obj->cursed != otmp->cursed || obj->blessed != otmp->blessed ||
  1215.        obj->no_charge != otmp->no_charge || 
  1216.        obj->otrapped != otmp->otrapped)
  1217.         return(FALSE);
  1218.  
  1219.     if((obj->olet==WEAPON_SYM || obj->olet==ARMOR_SYM) &&
  1220.         obj->rustfree != otmp->rustfree) return FALSE;
  1221.  
  1222.     if(obj->olet == FOOD_SYM && (obj->oeaten != otmp->oeaten ||
  1223.         obj->orotten != otmp->orotten))
  1224.         return(FALSE);
  1225.  
  1226.     if(obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
  1227.         if((obj->corpsenm != otmp->corpsenm) ||
  1228.             (ONAME(obj) && strcmp(ONAME(obj), ONAME(otmp))))
  1229.                 return FALSE;
  1230.     }
  1231.  
  1232. /* if they have names, make sure they're the same */
  1233.     if ( (obj->onamelth != otmp->onamelth &&
  1234.         ((obj->onamelth && otmp->onamelth) || obj->otyp == CORPSE)
  1235.          ) ||
  1236.         (obj->onamelth && 
  1237.             strncmp(ONAME(obj), ONAME(otmp), (int)obj->onamelth)))
  1238.         return FALSE;
  1239.  
  1240. #ifdef NAMED_ITEMS
  1241.     if(is_artifact(obj) != is_artifact(otmp)) return FALSE;
  1242. #endif
  1243.  
  1244.     if(obj->known == otmp->known || 
  1245.         !objects[otmp->otyp].oc_uses_known) {
  1246.         return(objects[obj->otyp].oc_merge);
  1247.     } else return(FALSE);
  1248. }
  1249.  
  1250. #endif /* OVL1 */
  1251. #ifdef OVLB
  1252.  
  1253. int
  1254. doprgold(){
  1255.     if(!u.ugold)
  1256.         You("do not carry any gold.");
  1257.     else
  1258.         You("are carrying %ld gold piece%s.", u.ugold, plur(u.ugold));
  1259.     return 0;
  1260. }
  1261.  
  1262. int
  1263. doprwep()
  1264. {
  1265.     if(!uwep) You("are empty %s.", body_part(HANDED));
  1266.     else prinv(uwep);
  1267.     return 0;
  1268. }
  1269.  
  1270. int
  1271. doprarm(){
  1272.     if(!wearing_armor())
  1273.         You("are not wearing any armor.");
  1274.     else {
  1275. #ifdef SHIRT
  1276.         char lets[8];
  1277. #else
  1278.         char lets[7];
  1279. #endif
  1280.         register int ct = 0;
  1281.  
  1282. #ifdef SHIRT
  1283.         if(uarmu) lets[ct++] = obj_to_let(uarmu);
  1284. #endif
  1285.         if(uarm) lets[ct++] = obj_to_let(uarm);
  1286.         if(uarmc) lets[ct++] = obj_to_let(uarmc);
  1287.         if(uarmh) lets[ct++] = obj_to_let(uarmh);
  1288.         if(uarms) lets[ct++] = obj_to_let(uarms);
  1289.         if(uarmg) lets[ct++] = obj_to_let(uarmg);
  1290.         if(uarmf) lets[ct++] = obj_to_let(uarmf);
  1291.         lets[ct] = 0;
  1292.         doinv(lets);
  1293.     }
  1294.     return 0;
  1295. }
  1296.  
  1297. int
  1298. doprring(){
  1299.     if(!uleft && !uright)
  1300.         You("are not wearing any rings.");
  1301.     else {
  1302.         char lets[3];
  1303.         register int ct = 0;
  1304.  
  1305.         if(uleft) lets[ct++] = obj_to_let(uleft);
  1306.         if(uright) lets[ct++] = obj_to_let(uright);
  1307.         lets[ct] = 0;
  1308.         doinv(lets);
  1309.     }
  1310.     return 0;
  1311. }
  1312.  
  1313. int
  1314. dopramulet(){
  1315.     if (!uamul)
  1316.         You("are not wearing an amulet.");
  1317.     else
  1318.         prinv(uamul);
  1319.     return 0;
  1320. }
  1321.  
  1322. int
  1323. doprtool(){
  1324.     register struct obj *otmp;
  1325.     register int ct=0;
  1326.     char lets[3]; /* Maximum: pick-axe, blindfold */
  1327.  
  1328.     for(otmp = invent; otmp; otmp = otmp->nobj) {
  1329.         if (((otmp->owornmask & W_TOOL) && otmp->olet==TOOL_SYM)
  1330.            || (otmp==uwep &&
  1331.            (otmp->otyp==PICK_AXE || otmp->otyp==TIN_OPENER)))
  1332.             lets[ct++] = obj_to_let(otmp);
  1333.     }
  1334.     lets[ct] = 0;
  1335.     if (!ct) You("are not using any tools.");
  1336.     else doinv(lets);
  1337.     return 0;
  1338. }
  1339.  
  1340. int
  1341. digit(c)
  1342. char c;
  1343. {
  1344.     return(c >= '0' && c <= '9');
  1345. }
  1346.  
  1347. /*
  1348.  * uses up an object that's on the floor, charging for it as necessary
  1349.  */
  1350. void
  1351. useupf(obj)
  1352. register struct obj *obj;
  1353. {
  1354.     register struct obj *otmp;
  1355.  
  1356.     /* burn_floor_paper() keeps an object pointer that it tries to
  1357.      * useupf() multiple times, so obj must survive if plural */
  1358.     if(obj->quan > 1)
  1359.         otmp = splitobj(obj, (int)obj->quan - 1);
  1360.     else
  1361.         otmp = obj;
  1362.     addtobill(otmp, FALSE);
  1363.     delobj(otmp);
  1364. }
  1365.  
  1366. #endif /* OVLB */
  1367. #ifdef OVL1
  1368.  
  1369. /*
  1370.  * Convert from a symbol to a string for printing object classes
  1371.  *
  1372.  * Names from objects.h
  1373.  * char obj_symbols[] = {
  1374.  *    ILLOBJ_SYM, AMULET_SYM, FOOD_SYM, WEAPON_SYM, TOOL_SYM,
  1375.  *    BALL_SYM, CHAIN_SYM, ROCK_SYM, ARMOR_SYM, POTION_SYM, SCROLL_SYM,
  1376.  *    WAND_SYM, [SPBOOK_SYM], RING_SYM, GEM_SYM, 0 };
  1377.  */
  1378.  
  1379. static const char NEARDATA *names[] = {
  1380.     "Illegal objects", "Amulets", "Comestibles", "Weapons",
  1381.     "Tools", "Iron balls", "Chains", "Boulders/Statues", "Armor",
  1382.     "Potions", "Scrolls", "Wands",
  1383. #ifdef SPELLS
  1384.     "Spellbooks",
  1385. #endif
  1386.     "Rings", "Gems"};
  1387.  
  1388. char *
  1389. let_to_name(let)
  1390. char let;
  1391. {
  1392.     const char *pos = index(obj_symbols, let);
  1393.     /* arbitrary buffer size by Tom May (tom@uw-warp) */
  1394.     static char NEARDATA *buf = NULL;
  1395.  
  1396.     if (buf == NULL)
  1397.         buf = (char *) alloc ((unsigned)(strlen(HI)+17+strlen(HE)));
  1398. /* 
  1399.    THE ALLOC() *MUST* BE BIG ENOUGH TO ACCOMODATE THE LONGEST NAME PLUS A
  1400.    NULL BYTE: 
  1401.             Boulders/Statues   +  '\0'
  1402.             1234567890123456 = 16 + 1 = 17
  1403. */
  1404.     if (pos == NULL) pos = obj_symbols;
  1405.     if (HI && HE)
  1406.         Sprintf(buf, "%s%s%s", HI, names[pos - obj_symbols], HE);
  1407.     else
  1408.         Sprintf(buf, "%s", names[pos - obj_symbols]);
  1409.     return (buf);
  1410. }
  1411.  
  1412. #endif /* OVL1 */
  1413. #ifdef OVLB
  1414.  
  1415. void
  1416. reassign()
  1417. {
  1418.     register int i;
  1419.     register struct obj *obj;
  1420.  
  1421.     for(obj = invent, i = 0; obj; obj = obj->nobj, i++)
  1422.         obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26);
  1423.     lastinvnr = i;
  1424. }
  1425.  
  1426. #endif /* OVLB */
  1427.